package com.molichuxing.gateway.bff.car.services.impl;

import java.time.LocalDate;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.apache.commons.lang3.StringUtils;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import com.molichuxing.framework.utils.DateUtil;
import com.molichuxing.framework.utils.EmailUtil;
import com.molichuxing.framework.utils.ObjectCastUtil;
import com.molichuxing.gateway.bff.car.convertor.Convert;
import com.molichuxing.gateway.bff.car.entity.response.AccidentDownloadVo;
import com.molichuxing.gateway.bff.car.entity.response.CarInsuranceVo;
import com.molichuxing.gateway.bff.car.entity.response.CarsViolationVo;
import com.molichuxing.gateway.bff.car.services.CarDownloadBffService;
import com.molichuxing.gateway.utils.PoiExcelUtil;
import com.molichuxing.gateway.utils.entity.UserEntity;
import com.molichuxing.services.business.dto.response.AccidentDownloadBizDto;
import com.molichuxing.services.business.dto.response.CarInsuranceDto;
import com.molichuxing.services.business.service.CarAccidentBizService;
import com.molichuxing.services.business.service.CarInsuranceBizService;
import com.molichuxing.services.infrastructure.dto.response.CarsViolationDto;
import com.molichuxing.services.infrastructure.dto.response.UserDto;
import com.molichuxing.services.infrastructure.service.CarViolationService;
import com.molichuxing.services.infrastructure.service.InsuranceCompanyService;
import com.molichuxing.services.infrastructure.service.InsuranceService;
import com.molichuxing.services.infrastructure.service.UserService;
import com.molichuxing.services.property.CarInsuranceTypeEnum;

@Service("carDownloadBffService")
public class CarDownloadBffServiceImpl implements CarDownloadBffService {

	@Value("${email_account}")
	private String emailAccount;

	@Value("${email_password}")
	private String emailPassword;

	@Resource
	private CarViolationService carViolationService;

	@Resource
	private UserService userService;

	@Resource
	private CarAccidentBizService carAccidentBizService;

	@Resource
	private InsuranceCompanyService insuranceCompanyService;

	@Resource
	private CarInsuranceBizService carInsuranceBizService;

	@Resource
	private InsuranceService insuranceService;

	/**
	 * 查询导出车辆违章数据
	 * 
	 * @param map
	 *            ids(违章ids) licencePlate(车牌号) vin(车架号) status(违章处理状态)
	 *            userId(用户id) startDate（违章开始时间） endDate（违章结束时间）
	 * @return
	 */
	@Override
	public List<CarsViolationVo> getCarsViolationDownload(Map<String, Object> map) {

		carsViolationDownloadParams(map);

		List<CarsViolationDto> list = carViolationService.getCarsViolationDownload(map);
		if (null == list || list.isEmpty()) {
			return null;
		}
		List<Integer> userIds = new ArrayList<Integer>();
		for (CarsViolationDto dto : list) {
			userIds.add(dto.getUserId());
		}
		// 查询用户
		Map<Integer, UserDto> userMap = userService.getUsers(userIds);
		List<CarsViolationVo> result = new ArrayList<>(list.size());
		for (CarsViolationDto dto : list) {
			CarsViolationVo vo = new CarsViolationVo();
			BeanUtils.copyProperties(dto, vo);

			if (null != dto.getUserId()) {
				// 用户
				UserDto userDto = userMap == null ? null : userMap.isEmpty() ? null : userMap.get(dto.getUserId());
				// 用户手机号
				vo.setUserPhone(userDto == null ? null : userDto.getPhone());
				// 用户姓名
				vo.setRealName(userDto == null ? null : userDto.getRealName());
			}
			result.add(vo);
		}
		return result;
	}

	private void carsViolationDownloadParams(Map<String, Object> selectParams) {
		if (null != selectParams.get("ids")) {
			selectParams.put("ids", Arrays.asList(selectParams.get("ids").toString().split(",")));
			selectParams.remove("licencePlate");
			selectParams.remove("vin");
			selectParams.remove("status");
			selectParams.remove("startDate");
			selectParams.remove("endDate");
		} else {
			String userName = ObjectCastUtil.castString(selectParams.get("userName"));
			if (StringUtils.isNoneBlank(userName)) {
				UserDto userDto = userService.getUserByRealName(String.valueOf(selectParams.get("userName")));
				if (null == userDto) {
					selectParams.put("userId", 0);
				} else {
					selectParams.put("userId", userDto.getId());
				}
			}
		}
	}

	/**
	 * 查询车辆违章导出条数
	 * 
	 * @param selectParams
	 * @return
	 */
	@Override
	public Long getCarsViolationDownloadCount(Map<String, Object> selectParams) {
		carsViolationDownloadParams(selectParams);

		return carViolationService.getCarsViolationDownloadCount(selectParams);
	}

	/**
	 * 异步发送车辆违章导出数据
	 * 
	 * @param selectParams
	 * @return
	 */
	@Async
	@Override
	public Boolean getCarsViolationDownloadEmail(Map<String, Object> selectParams, UserEntity user) {
		List<CarsViolationVo> list = this.getCarsViolationDownload(selectParams);
		String fileName = "车辆违章列表(" + DateUtil.formatDate(LocalDate.now()) + ")";
		// 生成excel
		XSSFWorkbook xssBook = PoiExcelUtil.getCarsViolationDownload(list);
		// 发送邮件
		EmailUtil.sendMail(emailAccount, emailPassword, fileName, fileName, user.getAccount(), fileName + ".xlsx",
				xssBook);

		return true;
	}

	/**
	   * 查询事故报备导出数据
	   *    * ids id集合
	   *    * licencePlate 车牌号
	   *    * vin 车架号
	   *    * userName 用户名
	   *    * liabilityType 责任类型（0：无责，1：全责，2：主责，3：同责，4：次责）
	   *    * isCasualty 是否有人伤（0：无人伤，1：有人伤）
	   *    * accidentType 事故类型（1:单方事故，2：双方事故，3：多方事故，4：停放受损，5：车辆盗抢，6：车辆自燃，7：车辆涉水，8：重大自然灾害）
	   *    * accidentStartTime     出险开始时间
	   *    * accidentEndTime     出险结束时间
	   *    * status 事故状态（1：事故未确认，2：事故已确认，3：结案未确认，4：已结案，5：无效报备）
	   * @param map
	   * @return
	   */
	@Override
	public List<AccidentDownloadVo> getAccidentDownload(Map<String, Object> map) {

		accidentDownloadParams(map);

		List<AccidentDownloadBizDto> list = carAccidentBizService.getAccidentDownload(map);
		if(null == list || list.isEmpty()) {
			return null;
		}

		List<Integer> userIds = new ArrayList<Integer>();
		for (AccidentDownloadBizDto dto : list) {
			userIds.add(dto.getUserId());
		}
		// 查询用户
		Map<Integer, UserDto> userMap = userService.getUsers(userIds);
		List<AccidentDownloadVo> result = new ArrayList<>(list.size());
		for (AccidentDownloadBizDto dto : list) {
			AccidentDownloadVo vo = new AccidentDownloadVo();
			BeanUtils.copyProperties(dto, vo);

			if (null != dto.getUserId()) {
				// 用户
				UserDto userDto = userMap == null ? null : userMap.isEmpty() ? null : userMap.get(dto.getUserId());
				// 用户手机号
				vo.setUserPhone(userDto == null ? null : userDto.getPhone());
				// 用户姓名
				vo.setRealName(userDto == null ? null : userDto.getRealName());
			}
			result.add(vo);
		}
		return result;
	}

	public void accidentDownloadParams(Map<String, Object> selectParams) {
		if (null != selectParams.get("ids")) {
			selectParams.put("ids", Arrays.asList(selectParams.get("ids").toString().split(",")));
			selectParams.remove("licencePlate");
			selectParams.remove("vin");
			selectParams.remove("userName");
			selectParams.remove("liabilityType");
			selectParams.remove("isCasualty");
			selectParams.remove("accidentType");
			selectParams.remove("accidentStartTime");
			selectParams.remove("accidentEndTime");
		} else {
			if (selectParams.get("userName") != null) {
				UserDto userDto = userService.getUserByName(selectParams.get("userName").toString());
				if (userDto != null) {
					selectParams.put("userId", userDto.getId());
				}
			}
		}
	}

	/**
	 * 查询事故报备导出数据条数
	 * 
	 * @param selectParams
	 * @return
	 */
	@Override
	public Long getAccidentDownloadCount(Map<String, Object> selectParams) {
		accidentDownloadParams(selectParams);
		return carAccidentBizService.getAccidentDownloadCount(selectParams);
	}

	/**
	 * 异步发送事故报备导出数据
	 * 
	 * @param selectParams
	 * @param user
	 * @return
	 */
	@Override
	public Boolean getAccidentDownloadEmail(Map<String, Object> selectParams, UserEntity user) {
		List<AccidentDownloadVo> list = this.getAccidentDownload(selectParams);
		String fileName = "事故管理列表(" + DateUtil.formatDate(LocalDate.now()) + ")";
		// 生成excel
		XSSFWorkbook xssBook = PoiExcelUtil.getAccidentDownload(list);
		// 发送邮件
		EmailUtil.sendMail(emailAccount, emailPassword, fileName, fileName, user.getAccount(), fileName + ".xlsx",
				xssBook);

		return true;
	}


	/**
	 * 车辆保险信息导出
	 * 
	 * @param selectParams
	 * @return
	 */
	@Override
	public List<CarInsuranceVo> getInsuranceListDownload(Map<String, Object> selectParams) {
		List<CarInsuranceVo> result = null;
		long startTime = System.currentTimeMillis();
		// 参数信息
		selectParams = getInsuranceListDownloadMap(selectParams);
		// 查询
		List<CarInsuranceDto> carInsuranceDtos = carInsuranceBizService.getDownloadInsuranceList(selectParams);
		if (carInsuranceDtos == null || carInsuranceDtos.isEmpty()) {
			return result;
		}
		result = Convert.toCarInsuranceVo(carInsuranceDtos);
		long endTime1 = System.currentTimeMillis();
		float excTime1 = (float) (endTime1 - startTime) / 1000;
		System.out.println("查询车辆保险信息执行时间：" + excTime1 + "s");
		// 查询保险公司信息
		List<Integer> insuranceCompanyIds = insuranceService.getInsuranceCompanyIds(selectParams);
		Map<Integer, String> insuranceCompanyMap = insuranceCompanyService.getInsuranceCompanyName(insuranceCompanyIds);
		if (insuranceCompanyMap == null || insuranceCompanyMap.isEmpty()) {
			return result;
		}
		for (CarInsuranceVo carInsuranceVo : result) {
			carInsuranceVo.setInsuranceCompanyName(insuranceCompanyMap.get(carInsuranceVo.getInsuranceCompanyId()));
		}
		long endTime2 = System.currentTimeMillis();
		float excTime2 = (float) (endTime2 - endTime1) / 1000;
		System.out.println("查询保险公司名称信息执行时间：" + excTime2 + "s");
		return result;
	}

	/**
	 * 车辆保险导出数量
	 * 
	 * @param selectParams
	 * @return
	 */
	@Override
	public Long getInsuranceListDownloadCount(Map<String, Object> selectParams) {
		// 参数信息
		selectParams = getInsuranceListDownloadMap(selectParams);
		return carInsuranceBizService.getDownloadInsuranceCount(selectParams);
	}

	/**
	 * 车辆保险导出参数
	 * 
	 * @param selectParams
	 * @return
	 */
	private Map<String, Object> getInsuranceListDownloadMap(Map<String, Object> selectParams) {
		Object ids = selectParams.get("ids");
		if (ids != null) {
			Object type = selectParams.get("type");
			selectParams = new HashMap<>(2);
			selectParams.put("type", type);
			selectParams.put("ids", Arrays.asList(selectParams.get("ids").toString().split(",")));
		}
		return selectParams;
	}

	/**
	 * 车辆保险导出发邮件
	 * 
	 * @param selectParams
	 */
	@Async
	@Override
	public Boolean getInsuranceListDownloadEmail(Map<String, Object> selectParams, Integer carInsuranceType,
			UserEntity user) {
		List<CarInsuranceVo> insurances = getInsuranceListDownload(selectParams);
		String fileName = null;
		SXSSFWorkbook sxssBook = null;
		if (carInsuranceType == CarInsuranceTypeEnum.COMPULSORY_INSURANCE.getValue()) {
			// 交强险
			// 文件名
			fileName = "交强险列表(" + DateUtil.formatDate(LocalDate.now()) + ").xlsx";
			// 生成excel
			sxssBook = PoiExcelUtil.getInsuranceListDownload(insurances);
		} else if (carInsuranceType == CarInsuranceTypeEnum.COMMERCIAL_INSURANCE.getValue()) {
			// 商业险
			// 文件名
			fileName = "商业险列表(" + DateUtil.formatDate(LocalDate.now()) + ").xlsx";
			// 生成excel
			sxssBook = PoiExcelUtil.getCommercialInsuranceListDownload(insurances);
		}

		// 发送邮件
		EmailUtil.sendMail(emailAccount, emailPassword, "车辆保险数据", "车辆保险数据", user.getAccount(), fileName, sxssBook);

		return true;
	}
}
